<template>
  <div style="margin-bottom: 20px">
    <span style="font-size: 18px;font-weight: bold">
      从真实的维基文段中截取一句话作为提示输入模型中，然后请从模型生成的文段和真实的维基文段中选出真实的那一个。数据量：{{totalSamples}}
    </span>
  </div>
  <el-row>
    <el-col :span="12">
      <el-alert
          :title="searchAlertText"
          type="warning"
          style="margin-bottom: 10px;"
          v-show="showSearchAlert"
          @close="onSearchAlertClose"
          closable
      />
      <div style="text-align: left">
        <el-input style="width: 120px" class="item" :placeholder="'1 ≤ id ≤ ' + totalSamples"
                  v-model="searchingIndex" :disabled="changeSampleLoading">
        </el-input>
        <el-button @click="onSearchButtonClick" class="item" round v-loading="changeSampleLoading">
          <i class="el-icon-search"></i>
          查找指定样例
        </el-button>
      </div>
    </el-col>
    <el-col :span="12">
      <div style="text-align: right">
        <el-button-group v-loading="changeSampleLoading">
          <el-button type="primary" round @click="onPreviousSampleClick">上一样例</el-button>
          <el-button type="primary" round @click="onRandomSampleClick">随机样例</el-button>
          <el-button type="primary" round @click="onNextSampleClick">下一样例</el-button>
        </el-button-group>
      </div>
    </el-col>
  </el-row>
  <el-divider/>
  <el-card class="box-card" v-loading="changeSampleLoading">
    <template #header>
      <div class="card-header">
        <h3 style="display: inline">样例{{ currentSampleIndex + 1 }}：</h3>
      </div>
    </template>
    <div class="text item" v-html="currentSamplePrompt"/>
    <el-divider/>
    <div style="text-align: right">
      <el-button type="primary" round @click="onGenerateClick">生成</el-button>
    </div>
    <el-divider/>
    <generate-parameter-setter ref="generateParameterSetter" editable/>
  </el-card>
  <div v-for="each in resultCardList" :key="'wiki-generate-card-' + each.cardIndex">
    <el-divider/>
    <wiki-generate-task-card
        :sample-id="each.index" :prompt="each.prompt"
        :card-index="each.cardIndex"
        :max-length="each.maxLength"
        :temperature="each.temperature"
        :top-k="each.topK"
        :top-p="each.topP"
        @close="onCardClose(each.cardIndex)"/>
  </div>
</template>

<script>
import WikiGenerateTaskCard from "./WikiGenerateTaskCard.vue";
import {defineComponent, ref} from 'vue'
import {ElMessage} from "element-plus";
import GenerateParameterSetter from "./GenerateParameterSetter.vue";

export default defineComponent({
  name: "WikiGenerateTask",
  components: {
    WikiGenerateTaskCard,
    GenerateParameterSetter
  },
  data() {
    return {
      resultCardList: [],
      resultCardIndex: 0,
      totalSamples: -1,
      currentSampleIndex: 0, // 0 <= currentSampleIndex < totalSamples
      currentSamplePrompt: '',
      showSearchAlert: false,
      searchAlertText: '',
      searchingIndex: ref(''),
      changeSampleLoading: true,
    }
  },
  mounted() {
    this.axios.get('/generate/sample').then(response => {
      this.totalSamples = response.data.samples
      this.changeSampleLoading = false
      this.onChangeSample(0)
    }).catch(err => {
      ElMessage('获取文本生成样例数失败, 详情见控制台')
      console.log(err)
    })
    this.axios.get('/generate/config').then(response => {
      this.$refs.generateParameterSetter.table.maxLength = response.data['max_length']
      this.$refs.generateParameterSetter.table.temperature = response.data['temperature']
      this.$refs.generateParameterSetter.table.topK = response.data['top_k']
      this.$refs.generateParameterSetter.table.topP = response.data['top_p']
      this.loading = false
    }).catch(err => {
      ElMessage('获取文本生成参数失败, 详情见控制台')
      console.log(err)
    })
  },
  methods: {
    onCardClose(cardIndex) {
      for (let i = 0; i < this.resultCardList.length; ++i) {
        if (this.resultCardList[i].cardIndex === cardIndex) {
          this.resultCardList.splice(i, 1);
          break;
        }
      }
    },
    onChangeSample(index) {
      this.changeSampleLoading = true
      this.axios.get('/generate/sample', {
        params: {
          index: index
        }
      }).then(response => {
        this.currentSamplePrompt = this.formatHTMLString(response.data.prompt)
        this.changeSampleLoading = false
      }).catch(err => {
        ElMessage('获取文本生成样例' + index + '失败, 详情见控制台')
        console.log(err)
        this.changeSampleLoading = false
      })
    },
    onNextSampleClick() {
      this.currentSampleIndex += 1
      this.checkCurrentSampleIndex()
      this.onChangeSample(this.currentSampleIndex)
    },
    onPreviousSampleClick() {
      this.currentSampleIndex -= 1
      this.checkCurrentSampleIndex()
      this.onChangeSample(this.currentSampleIndex)
    },
    onRandomSampleClick() {
      this.currentSampleIndex = Math.floor(Math.random() * this.totalSamples)
      this.checkCurrentSampleIndex()
      this.onChangeSample(this.currentSampleIndex)
    },
    checkCurrentSampleIndex() {
      if (this.currentSampleIndex < 0) {
        this.currentSampleIndex = this.totalSamples - 1
      } else if (this.currentSampleIndex >= this.totalSamples) {
        this.currentSampleIndex = 0
      }
    },
    onSearchButtonClick() {
      let index = Number(this.searchingIndex)
      if (!Number.isInteger(index) || index < 1 || index > this.totalSamples) {
        this.showSearchAlert = true
        this.searchAlertText = '请输入1到' + this.totalSamples + '的整数'
        return
      }
      this.currentSampleIndex = index - 1
      this.checkCurrentSampleIndex()
      this.onChangeSample(this.currentSampleIndex)
    },
    onGenerateClick() {
      let paramSetter = this.$refs.generateParameterSetter
      this.resultCardList.unshift({
        index: this.currentSampleIndex,
        prompt: this.currentSamplePrompt,
        cardIndex: this.resultCardIndex,
        maxLength: Number(paramSetter.table.maxLength),
        temperature: Number(paramSetter.table.temperature),
        topK: Number(paramSetter.table.topK),
        topP: Number(paramSetter.table.topP),
      })
      this.resultCardIndex += 1
    },
    onSearchAlertClose() {
      this.showSearchAlert = false
    },
    // todo: 转换为工具函数
    formatHTMLString(string) {
      // 回车
      string = string.replace(/\r\n/g, "<br>").replace(/\n/g, "<br>").replace(/\r/g, "<br>");
      return string
    },
  }
})
</script>

<style scoped>
.box-card {
  width: 100%;
  text-align: left;
  margin-top: 10px;
}

.item {
  margin: 5px;
}
</style>